package com.suray.basic.wcs.plc.pojo.oper.single;

import com.suray.basic.wcs.plc.config.resolver.PlcAnnotation;
import com.suray.basic.wcs.plc.core.PlcOffset;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.plc.pojo.DeviceBase;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.WcsFuncUtil;

import java.io.IOException;

/**
 * 自动横移机
 */
public class AutoTraversingOper extends DeviceBase implements DeviceInterface {

    final protected static int OPER_OFF = 0;
    final protected static int OPER_ON = 1;
    /*1：横移平台左横移；2：横移平台原位；3：横移机右横移；4：横移输送线正转；5：横移输送线反转；6：横移机输送机停止*/
    private static final int LEFT = 1;
    private static final int ORIGIN = 2;
    private static final int RIGHT = 3;
    private static final int FORWARD = 4;
    private static final int REVERSE = 5;

    private static final int CONVEYOR_FORWARD = 11;
    private static final int CONVEYOR_REVERSE = 12;
    private static final int CONVEYOR_STOP = 13;

    private static final int DOOR1_FORWARD = 21;
    private static final int DOOR1_REVERSE = 22;

    private static final int DOOR3_FORWARD = 31;
    private static final int DOOR3_REVERSE = 32;

    private static final PlcOffset DEVICE_TYPE = new PlcOffset(0, null);
    private static final PlcOffset IS_OPEN_SHAPE = new PlcOffset(17, 0);
    private static final PlcOffset IS_OPEN_BCR = new PlcOffset(17, 1);
    private static final PlcOffset IS_OPEN_OVERWEIGHT = new PlcOffset(17, 2);

    private static final PlcOffset STOP_STATE = new PlcOffset(18, 0);
    private static final PlcOffset CONTROLLER_MODE_MANUAL = new PlcOffset(18, 1);
    private static final PlcOffset CONTROLLER_MODE_AUTO = new PlcOffset(18, 2);
    private static final PlcOffset MANUAL_UP = new PlcOffset(18, 3);
    private static final PlcOffset MANUAL_DOWN = new PlcOffset(18, 4);
    private static final PlcOffset MANUAL_FORWARD = new PlcOffset(18, 5);
    private static final PlcOffset MANUAL_REVERSE = new PlcOffset(18, 6);
    private static final PlcOffset CLEAR_ERROR_1 = new PlcOffset(18, 7);
    private static final PlcOffset IS_CONTROL = new PlcOffset(18, 8);
    private static final PlcOffset DEVICE_STATE = new PlcOffset(18, 9);
    private static final PlcOffset ELEVATOR_STATE = new PlcOffset(18, 10);
    private static final PlcOffset CONVEYOR_STATE = new PlcOffset(18, 11);
    private static final PlcOffset ERROR_STATE = new PlcOffset(18, 12);
    private static final PlcOffset LIMIT1 = new PlcOffset(18, 13);
    private static final PlcOffset LIMIT3 = new PlcOffset(18, 14);
    private static final PlcOffset IN_CARGO_SIGNAL = new PlcOffset(18, 15);

    private static final PlcOffset OUT_CARGO_SIGNAL = new PlcOffset(19, 0);
    private static final PlcOffset IN_PLACE_SIGNAL_1 = new PlcOffset(19, 1);
    private static final PlcOffset IN_PLACE_SIGNAL_0 = new PlcOffset(19, 2);
    private static final PlcOffset IN_PLACE_SIGNAL_3 = new PlcOffset(19, 3);
    private static final PlcOffset AUTO_DOOR_RISE_1 = new PlcOffset(19, 4);
    private static final PlcOffset AUTO_DOOR_DROP_1 = new PlcOffset(19, 5);
    private static final PlcOffset AUTO_DOOR_ERROR_1 = new PlcOffset(19, 6);
    private static final PlcOffset AUTO_DOOR_RISE_3 = new PlcOffset(19, 7);
    private static final PlcOffset AUTO_DOOR_DROP_3 = new PlcOffset(19, 8);
    private static final PlcOffset AUTO_DOOR_ERROR_3 = new PlcOffset(19, 9);
    private static final PlcOffset AUTO_DOOR_OPEN_RUN_1 = new PlcOffset(19, 10);
    private static final PlcOffset AUTO_DOOR_CLOSE_RUN_1 = new PlcOffset(19, 11);
    private static final PlcOffset AUTO_DOOR_OPEN_RUN_3 = new PlcOffset(19, 12);
    private static final PlcOffset AUTO_DOOR_CLOSE_RUN_3 = new PlcOffset(19, 13);
    private static final PlcOffset ERROR_INFO = new PlcOffset(20, null);
    private static final PlcOffset CHECK_NO = new PlcOffset(21, null);
    private static final PlcOffset CURRENT_DEVICE_TYPE = new PlcOffset(22, null);

    //任务号
    private static final PlcOffset TASK_NO = new PlcOffset(25, null);
    //起点设备编号
    private static final PlcOffset TASK_START_LOCATION = new PlcOffset(26, null);
    //终点设备编号
    private static final PlcOffset TASK_END_LOCATION = new PlcOffset(27, null);

    //设备类型 写
    private static final int DEVICETYPE = 0;
    //位移量 写
    private static final int MOVEMENT = 1;
    //横移自动速度 写
    private static final int TRAVERSE_AUTO_SPEED = 2;
    //横移自动加速时间 写
    private static final int TRAVERSE_AUTO_ACC = 3;
    //横移自动减速时间 写
    private static final int TRAVERSE_AUTO_DEC = 4;
    //横移手动速度 写
    private static final int TRAVERSE_MANUAL_SPEED = 5;
    //横移手动加速时间 写
    private static final int TRAVERSE_MANUAL_ACC = 6;
    //横移手动减速时间 写
    private static final int TRAVERSE_MANUAL_DEC = 7;
    //输送线自动速度 写
    private static final int CONVEYOR_AUTO_SPEED = 8;
    //输送线自动加速时间 写
    private static final int CONVEYOR_AUTO_ACC = 9;
    //输送线自动减速时间 写
    private static final int CONVEYOR_AUTO_DEC = 10;
    //输送线手动速度 写
    private static final int CONVEYOR_MANUAL_SPEED = 11;
    //输送线手动加速时间 写
    private static final int CONVEYOR_MANUAL_ACC = 12;
    //输送线手动减速时间
    private static final int CONVEYOR_MANUAL_DEC = 13;
    //单体设备运行 写
    private static final int TASK_ACTION = 14;
    //自动横移机 写
    private static final int AUTO_TRAVERSING = 16;
    //故障清除 写
    private static final int CLEAR_ERROR = 17;
    //下发输送任务
    private static final int SEND_TASK = 28;
    //清除任务信息
    private static final int CLEAR_TASK = 31;

    public AutoTraversingOper(PlcDeviceType plcDeviceType, int startNo, String deviceName, int deviceNo, Coord coord,
                              Location location, Coord lockLocation, long deviceId, Integer gridzMax,
                              Integer gridzRelative, int plcId) {
        super(plcDeviceType, startNo, deviceName, deviceNo, coord, location, lockLocation, deviceId, gridzMax,
                gridzRelative, plcId);
    }

    public Integer getTaskNo() {
        return readPlc(TASK_NO);
    }

    public Integer getTaskStartLocation() {
        return readPlc(TASK_START_LOCATION);
    }

    public Integer getTaskEndLocation() {
        return readPlc(TASK_END_LOCATION);
    }

    @PlcAnnotation("下发输送任务")
    public void sendConveryTask(int taskNo, int startDeviceNo, int endDeviceNo) throws IOException {
        String des = getDeviceStatus();
        while (getTaskNo() != 0) {
            setDeviceStatus("任务号不为0，不能下发任务：" + taskNo);
            WcsFuncUtil.delay(1000);
        }
        setDeviceStatus(des);

        LoggerUtil.info("下发自动横移机任务，设备：" + getDeviceName() + ", 任务编号：" + taskNo + ", 起点设备：" + startDeviceNo
                + ", 终点设备:" + endDeviceNo, this.getClass());
        int[] data = new int[3];
        data[0] = taskNo;
        data[1] = startDeviceNo;
        data[2] = endDeviceNo;
        oper("发送行驶任务", this.getClass(), SEND_TASK, 10, data);
    }

    @PlcAnnotation("清除任务编号")
    public void clearTaskNo() throws IOException {
        LoggerUtil.info("清除任务编号，设备：" + getDeviceName(), this.getClass());
        oper("清除任务编号", this.getClass(), CLEAR_TASK, 10, 1);
    }

    public Integer getDeviceType() {
        return readPlc(DEVICE_TYPE);
    }

    @PlcAnnotation("设置设备类型")
    public void setDeviceType()throws IOException {
        oper("设置设备类型", this.getClass(), DEVICETYPE,3,9);
    }

    public Integer getMovement() {
        return readPlc(new PlcOffset(MOVEMENT, null));
    }

    /**
     * 平台升位移量
     *
     * @return
     */
    @PlcAnnotation("平台升位移量")
    public void setPlatformRiseMovement() throws IOException {
        oper("平台升位移量", this.getClass(), MOVEMENT, 10, 11);
    }

    /**
     * 平台降位移量
     *
     * @return
     */
    @PlcAnnotation("平台降位移量")
    public void setPlatformDropMovement() throws IOException {
        oper("平台降位移量", this.getClass(), MOVEMENT, 10, 12);
    }

    /**
     * 设置横移自动速度
     *
     * @return
     */
    @PlcAnnotation("设置横移自动速度")
    public void setTraverseAutoSpeed(int speed) throws IOException {
        LoggerUtil.info("横移自动速度:" + speed, this.getClass());
        oper("设置横移自动速度", this.getClass(), TRAVERSE_AUTO_SPEED, 10, speed);
    }

    public Integer getTraverseAutoSpeed() {
        return readPlc(new PlcOffset(TRAVERSE_AUTO_SPEED, null));
    }

    /**
     * 设置横移自动加速时间
     *
     * @return
     */
    @PlcAnnotation("设置横移自动加速时间")
    public void setTraverseAutoAcc(int time) throws IOException {
        LoggerUtil.info("横移自动加速时间:" + time, this.getClass());
        oper("设置横移自动加速时间", this.getClass(), TRAVERSE_AUTO_ACC, 10, time);
    }

    public Integer getTraverseAutoAcc() {
        return readPlc(new PlcOffset(TRAVERSE_AUTO_ACC, null));
    }

    /**
     * 设置横移自动减速时间
     *
     * @return
     */
    @PlcAnnotation("设置横移自动减速时间")
    public void setTraverseAutoDec(int time) throws IOException {
        LoggerUtil.info("横移自动减速时间:" + time, this.getClass());
        oper("设置横移自动减速时间", this.getClass(), TRAVERSE_AUTO_DEC, 10, time);
    }

    public Integer getTraverseAutoDec() {
        return readPlc(new PlcOffset(TRAVERSE_AUTO_DEC, null));
    }

    /**
     * 设置横移手动速度
     *
     * @return
     */
    @PlcAnnotation("设置横移手动速度")
    public void setTraverseManualSpeed(int speed) throws IOException {
        LoggerUtil.info("横移手动速度:" + speed, this.getClass());
        oper("设置横移手动速度", this.getClass(), TRAVERSE_MANUAL_SPEED, 10, speed);
    }

    public Integer getTraverseManualSpeed() {
        return readPlc(new PlcOffset(TRAVERSE_MANUAL_SPEED, null));
    }

    /**
     * 设置横移手动加速时间
     *
     * @return
     */
    @PlcAnnotation("设置横移手动加速时间")
    public void setTraverseManualAcc(int time) throws IOException {
        LoggerUtil.info("横移手动加速时间:" + time, this.getClass());
        oper("设置横移手动加速时间", this.getClass(), TRAVERSE_MANUAL_ACC, 10, time);
    }

    public Integer getTraverseManualAcc() {
        return readPlc(new PlcOffset(TRAVERSE_MANUAL_ACC, null));
    }

    /**
     * 设置横移手动减速时间
     *
     * @return
     */
    @PlcAnnotation("设置横移手动减速时间")
    public void setTraverseManualDec(int time) throws IOException {
        LoggerUtil.info("横移手动减速时间:" + time, this.getClass());
        oper("设置横移手动减速时间", this.getClass(), TRAVERSE_MANUAL_DEC, 10, time);
    }

    public Integer getTraverseManualDec() {
        return readPlc(new PlcOffset(TRAVERSE_MANUAL_DEC, null));
    }

    /**
     * 设置输送线自动速度
     *
     * @return
     */
    @PlcAnnotation("设置输送线自动速度")
    public void setConveyorAutoSpeed(int speed) throws IOException {
        LoggerUtil.info("输送线自动速度:" + speed, this.getClass());
        oper("设置输送线自动速度", this.getClass(), CONVEYOR_AUTO_SPEED, 10, speed);
    }

    public Integer getConveyorAutoSpeed() {
        return readPlc(new PlcOffset(CONVEYOR_AUTO_SPEED, null));
    }

    /**
     * 设置输送线自动加速时间
     *
     * @return
     */
    @PlcAnnotation("设置输送线自动加速时间")
    public void setConveyorAutoAcc(int time) throws IOException {
        LoggerUtil.info("输送线自动加速时间:" + time, this.getClass());
        oper("设置输送线自动加速时间", this.getClass(), CONVEYOR_AUTO_ACC, 10, time);
    }

    public Integer getConveyorAutoAcc() {
        return readPlc(new PlcOffset(CONVEYOR_AUTO_ACC, null));
    }

    /**
     * 设置输送线自动减速时间
     *
     * @param time
     * @throws IOException
     */
    @PlcAnnotation("设置输送线自动减速时间")
    public void setConveyorAutoDec(int time) throws IOException {
        LoggerUtil.info("输送线自动减速时间:" + time, this.getClass());
        oper("设置输送线自动减速时间", this.getClass(), CONVEYOR_AUTO_DEC, 10, time);
    }

    public Integer getConveyorAutoDec() {
        return readPlc(new PlcOffset(CONVEYOR_AUTO_DEC, null));
    }

    /**
     * 设置输送线手动速度
     *
     * @return
     */
    @PlcAnnotation("设置输送线手动速度")
    public void setConveyorManualSpeed(int speed) throws IOException {
        LoggerUtil.info("输送线手动速度:" + speed, this.getClass());
        oper("设置输送线手动速度", this.getClass(), CONVEYOR_MANUAL_SPEED, 10, speed);
    }

    public Integer getConveyorManualSpeed() {
        return readPlc(new PlcOffset(CONVEYOR_MANUAL_SPEED, null));
    }

    /**
     * 设置输送线手动加速时间
     *
     * @param time
     * @throws IOException
     */
    @PlcAnnotation("设置输送线手动加速时间")
    public void setConveyorManualAcc(int time) throws IOException {
        LoggerUtil.info("输送线手动加速时间:" + time, this.getClass());
        oper("设置输送线手动加速时间", this.getClass(), CONVEYOR_MANUAL_ACC, 10, time);
    }

    public Integer getConveyorManualAcc() {
        return readPlc(new PlcOffset(CONVEYOR_MANUAL_ACC, null));
    }

    /**
     * 设置输送线手动减速时间
     *
     * @param time
     * @throws IOException
     */
    @PlcAnnotation(value = "设置输送线手动减速时间")
    public void setConveyorManualDec(int time) throws IOException {
        LoggerUtil.info("输送线手动减速时间:" + time, this.getClass());
        oper("设置输送线手动减速时间", this.getClass(), CONVEYOR_MANUAL_DEC, 10, time);
    }

    public Integer getConveyorManualDec() {
        return readPlc(new PlcOffset(CONVEYOR_MANUAL_DEC, null));
    }
    public Integer getTaskAction() {
        return readPlc(new PlcOffset(TASK_ACTION, null));
    }

    /**
     * 输送线正转
     *
     * @throws IOException
     */
    @PlcAnnotation("输送线正转")
    public void setConveyorForward() throws IOException {
        oper("输送线正转", this.getClass(), TASK_ACTION, 10, CONVEYOR_FORWARD);
    }

    /**
     * 输送线反转
     *
     * @throws IOException
     */
    @PlcAnnotation("输送线反转")
    public void setConveyorReverse() throws IOException {
        oper("输送线反转", this.getClass(), TASK_ACTION, 10, CONVEYOR_REVERSE);
    }

    /**
     * 输送线停止
     *
     * @throws IOException
     */
    @PlcAnnotation("输送线停止")
    public void setConveyorStop() throws IOException {
        oper("输送线停止", this.getClass(), TASK_ACTION, 10, CONVEYOR_STOP);
    }

    /**
     * 门是否关闭
     * @param door1 : 入库方向门，离货架近，否则为false:door3
     * @param open
     */
    public boolean checkDoorStatus(boolean door1, boolean open) {
        if (door1) {
            if (open) {
                return isAutoDoorRise1();
            } else {
                return isAutoDoorDrop1();
            }
        } else {
            if (open) {
                return isAutoDoorRise3();
            } else {
                return isAutoDoorDrop3();
            }
        }
    }

    /**
     * 自动门运行
     * @param door1 : 入库方向门，离货架近，否则为false:door3
     * @param open
     * @throws IOException
     */
    public void doorRun(boolean door1, boolean open) throws IOException {
        if (door1) {
            if (open) {
                setDoor1Forward();
            } else {
                setDoor1Reverse();
            }
        } else {
            if (open) {
                setDoor3Forward();
            } else {
                setDoor3Reverse();
            }
        }
    }

    /**
     * 自动门1正转
     *
     * @throws IOException
     */
    @PlcAnnotation("自动门1正转")
    public void setDoor1Forward() throws IOException {
        oper("自动门1正转", this.getClass(), TASK_ACTION, 10, DOOR1_FORWARD);
    }
    /**
     * 自动门1反转
     *
     * @throws IOException
     */
    @PlcAnnotation("自动门1反转")
    public void setDoor1Reverse() throws IOException {
        oper("自动门1反转", this.getClass(), TASK_ACTION, 10, DOOR1_REVERSE);
    }
    /**
     * 自动门3正转
     *
     * @throws IOException
     */
    @PlcAnnotation("自动门3正转")
    public void setDoor3Forward() throws IOException {
        oper("自动门3正转", this.getClass(), TASK_ACTION, 10, DOOR3_FORWARD);
    }
    /**
     * 自动门3反转
     *
     * @throws IOException
     */
    @PlcAnnotation("自动门3反转")
    public void setDoor3Reverse() throws IOException {
        oper("自动门3反转", this.getClass(), TASK_ACTION, 10, DOOR3_REVERSE);
    }
    /**
     * 平台左横移
     *
     * @return
     */
    @PlcAnnotation("平台左横移")
    public void platformLeft() throws IOException {
        oper("平台左横移", this.getClass(), AUTO_TRAVERSING, 10, LEFT);
    }

    /**
     * 平台右横移
     *
     * @return
     */
    @PlcAnnotation("平台右横移")
    public void platformRight() throws IOException {
        oper("平台右横移", this.getClass(), AUTO_TRAVERSING, 10, RIGHT);
    }

    /**
     * 平台原位
     *
     * @return
     */
    @PlcAnnotation("平台原位")
    public void platformInSitu() throws IOException {
        oper("平台原位", this.getClass(), AUTO_TRAVERSING, 10, ORIGIN);
    }

    /**
     * 自动横移机输送线运转
     * @param taskIn : 入库任务
     * @throws IOException
     */
    public void traverseConveryRun(boolean taskIn) throws IOException {
        if (taskIn) {
            traverseConveyorForward();
        } else {
            traverseConveyorForward();
        }
    }

    /**
     * 横移机输送线正转
     *
     * @return
     */
    @PlcAnnotation("横移机输送线正转")
    public void traverseConveyorForward() throws IOException {
        oper("横移机输送线正转", this.getClass(), TASK_ACTION, 10, FORWARD);
    }

    /**
     * 横移机输送线正转
     *
     * @return
     */
    @PlcAnnotation("横移机输送线正转")
    public void traverseConveyorReverse() throws IOException {
        oper("横移机输送线正转", this.getClass(), TASK_ACTION, 10, REVERSE);
    }

    public Integer getAutoTraversing() {
        return readPlc(new PlcOffset(AUTO_TRAVERSING, null));
    }

    /**
     * 故障清除
     * @return
     */
    @PlcAnnotation("自动升降机故障清除")
    public void setClearError() throws IOException {
        oper("自动升降机故障清除", this.getClass(), CLEAR_ERROR, 10, OPER_ON);
    }

    public boolean isClearError() {
        return readPlc(new PlcOffset(CLEAR_ERROR, null)) == 1;
    }

    public boolean isOpenShape() {
        return readPlc(IS_OPEN_SHAPE) == 1;
    }

    public boolean isOpenBcr() {
        return readPlc(IS_OPEN_BCR) == 1;
    }

    public boolean isOpenOverweight() {
        return readPlc(IS_OPEN_OVERWEIGHT) == 1;
    }

    /**
     * 急停
     * @return
     */
    public boolean isStopState() {
        return readPlc(STOP_STATE) == 1;
    }

    /**
     * 手动模式
     * @return
     */
    public boolean isControllerModeManual() {
        return readPlc(CONTROLLER_MODE_MANUAL) == 1;
    }

    /**
     * 自动模式
     * @return
     */
    public boolean isControllerModeAuto() {
        return readPlc(CONTROLLER_MODE_AUTO) == 1;
    }

    /**
     * 手动上升
     * @return
     */
    public boolean isManualUp() {
        return readPlc(MANUAL_UP) == 1;
    }

    /**
     * 手动下降
     * @return
     */
    public boolean isManualDown() {
        return readPlc(MANUAL_DOWN) == 1;
    }

    /**
     * 手动正转
     * @return
     */
    public boolean isManualForward() {
        return readPlc(MANUAL_FORWARD) == 1;
    }

    /**
     * 手动反转
     * @return
     */
    public boolean isManualReverse() {
        return readPlc(MANUAL_REVERSE) == 1;
    }

    /**
     * 清除故障状态
     * @return
     */
    public boolean isClearError1() {
        return readPlc(CLEAR_ERROR_1) == 1;
    }

    /**
     * 允许下发任务
     * @return
     */
    public boolean isControl() {
        return readPlc(IS_CONTROL) == 1;
    }

    /**
     * 运行中
     * @return
     */
    @Override
    public boolean isRunning() {
        return readPlc(DEVICE_STATE) == 1;
    }

    /**
     * 横移机升降运行
     * @return
     */
    public boolean isElevatorState() {
        return readPlc(ELEVATOR_STATE) == 1;
    }

    /**
     * 横移机输送线运行
     * @return
     */
    public boolean isConveyorState() {
        return readPlc(CONVEYOR_STATE) == 1;
    }

    /**
     * 故障
     * @return
     */
    @Override
    public boolean isError() {
        return readPlc(ERROR_STATE) == 1;
    }

    /**
     * 入库光电
     * @return
     */
    @Override
    public boolean inCargoSignal() {
        return readPlc(IN_CARGO_SIGNAL) == 1;
    }

    /**
     * 出库光电
     * @return
     */
    @Override
    public boolean outCargoSignal() {
        return readPlc(OUT_CARGO_SIGNAL) == 1;
    }

    /**
     * 横移机1方向到位
     * @return
     */
    public boolean isInPlaceSignal1() {
        return readPlc(IN_PLACE_SIGNAL_1) == 1;
    }

    /**
     * 横移机原点到位
     * @return
     */
    public boolean isInMidPlace() {
        return readPlc(IN_PLACE_SIGNAL_0) == 1;
    }

    /**
     * 横移机3方向到位
     * @return
     */
    public boolean isInPlaceSignal3() {
        return readPlc(IN_PLACE_SIGNAL_3) == 1;
    }

    public boolean isAutoDoorRise1() {
        return readPlc(AUTO_DOOR_RISE_1) == 1;
    }

    public boolean isAutoDoorDrop1() {
        return readPlc(AUTO_DOOR_DROP_1) == 1;
    }

    public boolean isAutoDoorError1() {
        return readPlc(AUTO_DOOR_ERROR_1) == 1;
    }

    public boolean isAutoDoorRise3() {
        return readPlc(AUTO_DOOR_RISE_3) == 1;
    }

    public boolean isAutoDoorDrop3() {
        return readPlc(AUTO_DOOR_DROP_3) == 1;
    }

    public boolean isAutoDoorError3() {
        return readPlc(AUTO_DOOR_ERROR_3) == 1;
    }

    public boolean isAutoDoorOpenRun1() {
        return readPlc(AUTO_DOOR_OPEN_RUN_1) == 1;
    }

    public boolean isAutoDoorCloseRun1() {
        return readPlc(AUTO_DOOR_CLOSE_RUN_1) == 1;
    }

    public boolean isAutoDoorOpenRun3() {
        return readPlc(AUTO_DOOR_OPEN_RUN_3) == 1;
    }
    public boolean isAutoDoorCloseRun3() {
        return readPlc(AUTO_DOOR_CLOSE_RUN_3) == 1;
    }



    @Override
    public Integer errorCode() {
        return readPlc(ERROR_INFO);
    }

    public Integer getCheckNo() {
        return readPlc(CHECK_NO);
    }

    public Integer getCurrentDeviceType() {
        return readPlc(CURRENT_DEVICE_TYPE);
    }

    @Override
    public boolean hasCargo() {
        return inCargoSignal() || outCargoSignal();
    }

    @Override
    public boolean permitRun() {
        return isControl() && !isRunning();
    }

    @Override
    public boolean canControl() {
        return isControl();
    }

    @Override
    public String toString() {
        return getDeviceName();
    }
}
